
/*=======[R E V I S I O N   H I S T O R Y]====================================*/
/** <VERSION>   <DATE>      <AUTHOR>     <REVISION LOG> */
/*@{*/
#define CMAC_AES_128_C
/*@}*/
/*=======[I N C L U D E S]====================================================*/
/*=======[Includes]===========================================================*/
/*@{*/
#include "CMAC_AES_128.h"
#include "aes_crypto.h"
/*@}*/
/*=======[Private define]=====================================================*/
/*=======[Private types]======================================================*/
/*=======[Private function prototypes]========================================*/
/*=======[Private variables]==================================================*/
/*=======[Private functions]==================================================*/

/* For CMAC Calculation */
static uint8 const_Rb[16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
};
static uint8 const_Zero[16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Basic Functions */
void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
{
    int i;
    for (i=0;i<16; i++)
    {

        out[i] = a[i] ^ b[i];
    }
}
/* AES-CMAC Generation Function */
static void leftshift_onebit(uint8 *input,uint8 *output)
{
    int i;
    uint8 overflow = 0;
    for ( i=15; i>=0; i-- ) {
        output[i] = input[i] << 1;
        output[i] |= overflow;
        overflow = (input[i] & 0x80)?1:0;
    }
    return;
}
static void AES_128(uint8 *mask,uint8 *seed,uint8 *out)
{

}
static void generate_subkey(uint8 *key, uint8 *K1, uint8 *K2)
{
    uint8 L[16];
    uint8 Z[16];
    uint8 tmp[16];
    int i;
    uint8 IVKey11[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    for ( i=0; i<16; i++ )
    {
    	Z[i] = 0;
    	L[i] = 0;
    }
//        AES_128(key,Z,L);
        int outlength = 16;
        Appl_Memset(&CtxVariable, 0u, sizeof(AES_CTX));
        Aes_CBC_Init(&CtxVariable,
    							key, 16u,
								IVKey11);

    	Aes_CBC_Update(&CtxVariable,Z,16,L,&outlength);

    if ( (L[0] & 0x80) == 0 ) {
/* If MSB(L) = 0, then K1 = L << 1 */
        leftshift_onebit(L,K1);
    } else {
/* Else K1 = ( L << 1 ) (+) Rb */
        leftshift_onebit(L,tmp);
        xor_128(tmp,const_Rb,K1);
    }
    if ( (K1[0] & 0x80) == 0 ) {
        leftshift_onebit(K1,K2);
    } else {
        leftshift_onebit(K1,tmp);
        xor_128(tmp,const_Rb,K2);
    }
    return;
}
static void padding ( uint8 *lastb, uint8 *pad, int length )
{
    int j;

/* original last block */
    for ( j=0; j<16; j++ ) {
        if ( j < length ) {
            pad[j] = lastb[j];
        } else if ( j == length ) {
            pad[j] = 0x80;
        } else {
            pad[j] = 0x00;
        }
    }
}



void CMAC_AES_128 ( uint8 *key, uint8 *input, uint32 length, uint8 *mac )
{
    uint8 X[16], Y[16], M_last[16], padded[16];
    uint8 K1[16], K2[16];
    int n, i, flag;
    int outlength = 16;
    generate_subkey(key, K1, K2);

    Appl_Memset(padded, 0u, 16);

    uint8 IVKey12[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    n = (length + 15) / 16;
    /* n is number of rounds */
    if (n == 0)
    {
        n = 1;
        flag = 0;
    }
    else
    {
        if ((length % 16) == 0)
        {
            /* last block is a complete block */
            flag = 1;
        }
        else
        {
            /* last block is not complete block */
            flag = 0;
        }
    }
    if (flag)
    {
        /* last block is complete block */
        xor_128(&input[16 * (n - 1)], K1, M_last);
    }
    else
    {
        padding(&input[16 * (n - 1)], padded, length % 16);
        xor_128(padded, K2, M_last);
    }
    for (i = 0; i < 16; i++)
    {
        X[i] = 0;
    }
    for (i = 0; i < (n -1 ); i++)
    {
        xor_128(X, &input[16 * i], Y);
        /* Y := Mi (+) X */
//        AES_128(key, Y, X);
        Appl_Memset(&CtxVariable, 0u, sizeof(AES_CTX));
        Aes_CBC_Init(&CtxVariable,
    							key, 16u,
    							IVKey12);
    	Aes_CBC_Update(&CtxVariable,Y,16,X, &outlength);
        /* X := AES-128(KEY, Y); */
    }
    xor_128(X, M_last, Y);
//    AES_128(key, Y, X);
    Appl_Memset(&CtxVariable, 0u, sizeof(AES_CTX));
    Aes_CBC_Init(&CtxVariable,
							key, 16u,
							IVKey12);
	Aes_CBC_Update(&CtxVariable,Y,16,X, &outlength);
    for (i = 0; i < 16; i++)
    {
        mac[i] = X[i];
    }
}
/*=======[E N D   O F   F I L E]==============================================*/
